package pe.com.cotelasa.scp.dao.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.hibernate.Criteria;

import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import pe.com.cotelasa.common.dao.DaoImpl;
import pe.com.cotelasa.common.dao.excepcion.DAOException;
import pe.com.cotelasa.scp.dao.IDAOOrdenCompraServicio;
import pe.com.cotelasa.scp.dominio.common.ESTADO_REGISTRO;
import pe.com.cotelasa.scp.dominio.common.util.UtilitarioFecha;
import pe.com.cotelasa.scp.entidad.OrdenCompraServicio;

/**
 * @author usuario
 */
@SuppressWarnings("serial")
@Repository("daoOrdenCompraServicio")
public class DAOOrdenCompraServicioImpl extends DaoImpl<OrdenCompraServicio, Integer> implements IDAOOrdenCompraServicio, Serializable {

    @Autowired
    private SessionFactory sessionFactory;

    @SuppressWarnings("unchecked")
    @Override
    @Transactional
    public Collection<OrdenCompraServicio> listarOrdenCompraServiciosConCodigo(OrdenCompraServicio ordenCS) throws DAOException {
        List<OrdenCompraServicio> listaOrdenCS = new ArrayList<OrdenCompraServicio>();
        try {
            sessionFactory.getCurrentSession().flush();
            listaOrdenCS = sessionFactory.getCurrentSession().createCriteria(OrdenCompraServicio.class)
                    .createAlias("idOrdenPedido", "op")
                    .add(Restrictions.eq("estadoRegistro", ESTADO_REGISTRO.ACTIVO.getValor()))
                    .add(Restrictions.ne("estadoOrden", ordenCS.getEstadoOrden()))
                    .add(Restrictions.eq("op.idEmpresa", ordenCS.getIdOrdenPedido().getIdEmpresa()))
                    .add(Restrictions.like("codigo", ordenCS.getCodigo()))
                    .list();

        } catch (Exception e) {
            throw new DAOException(e.getMessage(), e);
        }

        return listaOrdenCS;
    }
///////////////

    @SuppressWarnings("unchecked")
    @Override
    @Transactional
    public Collection<OrdenCompraServicio> listarOrdenCSConCodigoPorOP(OrdenCompraServicio ordenCS, String[] listaEstado) throws DAOException {
        List<OrdenCompraServicio> listaOrdenCS = new ArrayList<OrdenCompraServicio>();
        try {
            sessionFactory.getCurrentSession().flush();
            Criteria query = sessionFactory.getCurrentSession().createCriteria(OrdenCompraServicio.class)
                    .addOrder(Order.asc("fechaEmision"))
                    .add(Restrictions.eq("estadoRegistro", ESTADO_REGISTRO.ACTIVO.getValor()))
                    .add(Restrictions.not(Restrictions.in("estadoOrden", listaEstado)))
                    .add(Restrictions.like("tipo", ordenCS.getTipo()));

            if (ordenCS.getIdOrdenPedido().getId() == 0) {
                query = query.add(Restrictions.isNull("idOrdenPedido"));
            } else {
                query = query.add(Restrictions.eq("idOrdenPedido.id", ordenCS.getIdOrdenPedido().getId()));
            }

            if (ordenCS.getFormaPago() != null) {
                query = query.add(Restrictions.eq("formaPago", ordenCS.getFormaPago()));
            }

            listaOrdenCS = query.list();
        } catch (Exception e) {
            throw new DAOException(e.getMessage(), e);
        }

        return listaOrdenCS;
    }

    @SuppressWarnings("unchecked")
    @Override
    @Transactional
    public Collection<OrdenCompraServicio> listarOrdenCompraServicioPorNroOrden(
            String nroOrden, String estadoOrdenOS, int idEmpresa) throws DAOException {
        List<OrdenCompraServicio> listaOrdenCS = new ArrayList<OrdenCompraServicio>();
        try {
            sessionFactory.getCurrentSession().flush();
            listaOrdenCS = sessionFactory.getCurrentSession().createCriteria(OrdenCompraServicio.class)
                    .createAlias("idOrdenPedido", "op")
                    .add(Restrictions.eq("estadoRegistro", ESTADO_REGISTRO.ACTIVO.getValor()))
                    .add(Restrictions.eq("estadoOrden", "" + OrdenCompraServicio.ESTADO_ORDEN_SC.ABIERTO.getValor()))
                    .add(Restrictions.eq("op.estadoPedido", estadoOrdenOS))
                    .add(Restrictions.eq("op.codigoOrdenPedido", nroOrden))
                    .add(Restrictions.eq("op.idEmpresa.id", idEmpresa))
                    .addOrder(Order.asc("codigo"))
                    .list();

        } catch (Exception e) {
            throw new DAOException(e.getMessage(), e);
        }
        return listaOrdenCS;
    }

    @Override
    public OrdenCompraServicio obtenerOrdenCSPorCodigo(OrdenCompraServicio ordenCS)
            throws DAOException {
        OrdenCompraServicio ordenCompraServicio = null;
        try {
            ordenCompraServicio = (OrdenCompraServicio) sessionFactory.getCurrentSession()
                    .createCriteria(OrdenCompraServicio.class)
                    .createAlias("idOrdenPedido", "op")
                    .add(Restrictions.eq("codigo", ordenCS.getCodigo()))
                    .add(Restrictions.eq("op.idEmpresa", ordenCS.getIdOrdenPedido().getIdEmpresa()))
                    .add(Restrictions.eq("estadoRegistro", ESTADO_REGISTRO.ACTIVO.getValor())).uniqueResult();
        } catch (Exception e) {
            throw new DAOException(e.getMessage(), e);
        }
        return ordenCompraServicio;
    }
///////////

    @SuppressWarnings("unchecked")
    @Override
    @Transactional
    public Collection<OrdenCompraServicio> buscarOrdenCompraServiciosPorFiltro(OrdenCompraServicio ordenCS, Date fechaInicio, Date fechaFinal) throws DAOException {
        List<OrdenCompraServicio> listaOrdenCS = new ArrayList<OrdenCompraServicio>();
        try {
            sessionFactory.getCurrentSession().flush();
            Criteria query = sessionFactory.getCurrentSession().createCriteria(OrdenCompraServicio.class)
                    .addOrder(Order.desc("id"))
                    .add(Restrictions.eq("estadoRegistro", ESTADO_REGISTRO.ACTIVO.getValor()))
                    .add(Restrictions.like("estadoOrden", "%" + ordenCS.getEstadoOrden() + "%"))
                    .add(Restrictions.like("codigo", "%" + ordenCS.getCodigo() + "%"))
                    .add(Restrictions.like("descripcion", "%" + ordenCS.getDescripcion() + "%"))
                    .add(Restrictions.eq("idEmpresa", ordenCS.getIdEmpresa()))
                    .add(Restrictions.like("tipo", "%" + ordenCS.getTipo() + "%"));
            if (ordenCS.getServicio() != null) {
                query = query.add(Restrictions.like("servicio", "%" + ordenCS.getServicio() + "%"));
            }
            if (ordenCS.getIdProveedor() != null) {
                query = query.createAlias("idProveedor", "p")
                        .add(Restrictions.like("p.razonSocial", "%" + ordenCS.getIdProveedor().getRazonSocial() + "%"));
            }
            if (ordenCS.getIdCategoriaArticulo() != null && ordenCS.getIdCategoriaArticulo().getId() != 0) {
                query = query.createAlias("idCategoriaArticulo", "c")
                        .add(Restrictions.eq("c.idCategoriaArticulo.id", ordenCS.getIdCategoriaArticulo().getId()));
            }
            
            if (ordenCS.getIdOrdenPedido().getId() == 0) {
                query = query.add(Restrictions.isNull("idOrdenPedido"));
            } else if (ordenCS.getIdOrdenPedido().getId() != null && ordenCS.getIdOrdenPedido().getId() != -1) {
                query = query.add(Restrictions.eq("idOrdenPedido", ordenCS.getIdOrdenPedido()));
            }


            if (fechaInicio == null && fechaFinal == null) {
                listaOrdenCS = query.addOrder(Order.asc("codigo")).list();
            } else if (fechaInicio != null && fechaFinal != null) {
                listaOrdenCS = query.add(Restrictions.ge("fechaEmision", fechaInicio)).add(Restrictions.le("fechaEmision", fechaFinal)).addOrder(Order.asc("codigo")).list();
            } else if (fechaInicio == null) {
                listaOrdenCS = query.add(Restrictions.le("fechaEmision", fechaFinal)).addOrder(Order.asc("codigo")).list();
            } else if (fechaFinal == null) {
                listaOrdenCS = query.add(Restrictions.ge("fechaEmision", fechaInicio)).addOrder(Order.asc("codigo")).list();
            }

        } catch (Exception e) {
            throw new DAOException(e.getMessage(), e);
        }
        return listaOrdenCS;

    }

    @SuppressWarnings("unchecked")
    @Override
    @Transactional
    public Collection<OrdenCompraServicio> buscarOrdenCSReporte(
            OrdenCompraServicio ordenCS,
            String[] listaEstado,
            Date fechaInicio,
            Date fechaFinal) throws DAOException {
        List<OrdenCompraServicio> listaOrdenCS = new ArrayList<OrdenCompraServicio>();
        try {
            sessionFactory.getCurrentSession().flush();
            Criteria query = sessionFactory.getCurrentSession().createCriteria(OrdenCompraServicio.class)
                    .createAlias("idOrdenPedido", "op")
                    .addOrder(Order.desc("id"))
                    .add(Restrictions.eq("estadoRegistro", ESTADO_REGISTRO.ACTIVO.getValor()))
                    .add(Restrictions.in("estadoOrden", listaEstado))
                    .add(Restrictions.eq("idEmpresa", ordenCS.getIdEmpresa()))
                    .add(Restrictions.eq("op.tipoOp", ordenCS.getIdOrdenPedido().getTipoOp()))
                    .add(Restrictions.like("tipo", "%" + ordenCS.getTipo() + "%"));

            if (ordenCS.getIdOrdenPedido().getId() != null) {
                query = query.add(Restrictions.eq("idOrdenPedido", ordenCS.getIdOrdenPedido()));
            }

            if (fechaInicio == null && fechaFinal == null) {
                listaOrdenCS = query.list();
            } else if (fechaInicio != null && fechaFinal != null) {
                listaOrdenCS = query.add(Restrictions.ge("fechaEmision", fechaInicio)).add(Restrictions.le("fechaEmision", fechaFinal)).list();
            } else if (fechaInicio == null) {
                listaOrdenCS = query.add(Restrictions.le("fechaEmision", fechaFinal)).list();
            } else if (fechaFinal == null) {
                listaOrdenCS = query.add(Restrictions.ge("fechaEmision", fechaInicio)).list();
            }

        } catch (Exception e) {
            throw new DAOException(e.getMessage(), e);
        }
        return listaOrdenCS;

    }

    @Override
    public int buscarCantidadOC(OrdenCompraServicio ordenCompra) throws DAOException {
        sessionFactory.getCurrentSession().flush();
        String[] listaEstado = {"" + OrdenCompraServicio.ESTADO_ORDEN_SC.ABIERTO.getValor(),
            "" + OrdenCompraServicio.ESTADO_ORDEN_SC.CERRADO.getValor()};

        Long a = (Long) sessionFactory.getCurrentSession().createCriteria(OrdenCompraServicio.class)
                .createAlias("idCategoriaArticulo", "c")
                .add(Restrictions.eq("c.idCategoriaArticulo", ordenCompra.getIdCategoriaArticulo().getIdCategoriaArticulo()))
                .add(Restrictions.eq("estadoRegistro", String.valueOf(ESTADO_REGISTRO.ACTIVO.getValor())))
                .add(Restrictions.eq("idEmpresa", ordenCompra.getIdEmpresa()))
                .add(Restrictions.in("estadoOrden", listaEstado))
                .add(Restrictions.eq("tipo", "C"))
                .add(Restrictions.le("fechaEmision", UtilitarioFecha.toEndOfYear(UtilitarioFecha.obtenerAnio(ordenCompra.getFechaEmision()))))
                .add(Restrictions.ge("fechaEmision", UtilitarioFecha.toStartOfYear(UtilitarioFecha.obtenerAnio(ordenCompra.getFechaEmision()))))
                .setProjection(Projections.rowCount())
                .uniqueResult();

        return a.intValue();
        //.list().get(0);
    }

    @Override
    public int buscarCantidadOS(OrdenCompraServicio ordenServicio) throws DAOException {
        sessionFactory.getCurrentSession().flush();
        String[] listaEstado = {"" + OrdenCompraServicio.ESTADO_ORDEN_SC.ABIERTO.getValor(),
            "" + OrdenCompraServicio.ESTADO_ORDEN_SC.CERRADO.getValor()};
        Long a = (Long) sessionFactory.getCurrentSession().createCriteria(OrdenCompraServicio.class)
                .add(Restrictions.eq("servicio", ordenServicio.getServicio()))
                .add(Restrictions.eq("estadoRegistro", String.valueOf(ESTADO_REGISTRO.ACTIVO.getValor())))
                .add(Restrictions.eq("idEmpresa", ordenServicio.getIdEmpresa()))
                .add(Restrictions.in("estadoOrden", listaEstado))
                .add(Restrictions.eq("tipo", "S"))
                .add(Restrictions.le("fechaEmision", UtilitarioFecha.toEndOfYear(UtilitarioFecha.obtenerAnio(ordenServicio.getFechaEmision()))))
                .add(Restrictions.ge("fechaEmision", UtilitarioFecha.toStartOfYear(UtilitarioFecha.obtenerAnio(ordenServicio.getFechaEmision()))))
                .setProjection(Projections.rowCount())
                .uniqueResult();

        return a.intValue();
        //.list().get(0);
    }
}
